package com.atguigu.gmall.rabbit.config;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.rabbit.entity.GmallCorrelationData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @Author: 李旭
 * @Time: 9:14
 * @Description:
 *
 *   自定义应答实现类
 *
 *       接收交换机应答
 *       接收队称的应答
 */
@Component //SpringIOC容器中
@Slf4j
public class MQProducerAckConfig implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate redisTemplate;
    @PostConstruct //构造器执行 就执行init 方法
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
    }

    //交换机应答
    //1:应答的时机  成功  失败 都应答
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        //ack ：true 成功应答   false: 失败应答
        if(ack){
            System.out.println("成功应答：原因是：" + cause);
        }else{
            System.out.println("失败应答：原因是：" + cause);
            //重新发送消息

            retrySendMessage(correlationData);


        }
    }

    //重新发送
    private void retrySendMessage(CorrelationData correlationData) {
        GmallCorrelationData correlationData1 = (GmallCorrelationData) correlationData;
        //重新发送2次
        int retryCount = correlationData1.getRetryCount();
        retryCount++;
        correlationData1.setRetryCount(retryCount);
        if(retryCount <= 2){
            //更新Redis中重发消息对象
            redisTemplate.opsForHash().put("rabbit_prefix",correlationData1.getId(),
                    JSONObject.toJSONString(correlationData1));
            log.info("成功重新发送:{}" + JSONObject.toJSONString(correlationData1) );
            //重新发送
            rabbitTemplate.convertAndSend(correlationData1.getExchange(),
                    correlationData1.getRoutingKey(),correlationData1.getMessage(),
                    correlationData1);
        }else{
            //打印日志
            log.info("剩余发送次数已经用完:{}" + JSONObject.toJSONString(correlationData1));
        }
    }

    //队列应答
    //时机： 只能失败了才应答
    @Override
    public void returnedMessage(Message message,
                                int replyCode,
                                String replyText,
                                String exchange,
                                String routingKey) {

        System.out.println("msg:" + new String(message.getBody()));
        System.out.println("replyCode:" + replyCode);
        System.out.println("replyText:" + replyText);
        System.out.println("exchange:" + exchange);
        System.out.println("routingKey:" + routingKey);

        Object uuid = message.getMessageProperties().
                getHeader("spring_returned_message_correlation");
        //重新发送  次数
        String rabbit_prefix = (String) redisTemplate.opsForHash().get("rabbit_prefix", uuid);
        GmallCorrelationData gmallCorrelationData = JSONObject.
                parseObject(rabbit_prefix, GmallCorrelationData.class);
        //判断是否为插件的延迟消息
        if(gmallCorrelationData.isDelay()){
            return;
        }
        //重新发送
        //retrySendMessage(gmallCorrelationData);
    }
}
